<html>
    <head>
        <title>分布式锁</title>
    </head>
    <body>
        <script>
            // 分布式锁

                    /*
                        分布式锁是一种管理多个试图访问同意资源的应用程序的技术，主要目的是只允许多个应用程序中的一个同时访问同一资源，

                        否则，从各个应用程序访问同一个对象可能会破坏资源的价值。

                        ABP当前的分布式锁实现基于分布式锁库：  https://github.com/madelson/DistributedLock
                    
                    */

                    /*
                        一、安装

                            1、第一步： 安装模块

                                    你可以打开命令行终端并键入以下命令将 "Volo.Abp.DistributedLocking" 包安装到你的项目中：

                                        "abp add-package Volo.Abp.DistributedLocking"

                                    这个包提供了分布式锁系统所需的API，但是，你应该在使用它之前配置一个"提供程序"。

                            2、第二步：  配置提供程序

                                            分布式锁库为锁定 "提供了各种实现" ，例如 Redis 和 Zookeeper.

                                            例如，如果你想使用 Redis提供程序，你应该将 " DistributedLock.Redis" NuGet 包添加到你的项目中，

                                            然后将以下代码添加到ABP模块类的 ConfigureServices 方法中：

                                                    using Medallion.Threading;
                                                    using Medallion.Threading.Redis;

                                                    namespace AbpDemo
                                                    {
                                                        [DependsOn(
                                                                typeof(AbpDistributedLockingModule) // 依赖分布式锁模块
                                                                // 其他模块依赖...
                                                        )]
                                                        public class MyModule : AbpModule
                                                        {
                                                            public override void ConfigureServices(ServiceConfigurationContext context)
                                                            {
                                                                var configuration = context.Services.GetConfiguration();
                                                            
                                                                // 注册分布式锁提供程序
                                                                context.Services.AddSingleton<IDistributedLockProvider>(sp =>
                                                                {
                                                                    var connection = ConnectionMultiplexer
                                                                        .Connect(configuration["Redis:Configuration"]);
                                                                    return new 
                                                                        RedisDistributedSynchronizationProvider(connection.GetDatabase());
                                                                });
                                                            }
                                                        }
                                                    }

                                
                                            此代码从配置文件中获取 Redis 连接字符串，因此你可以将以下行添加到 appsettings.json 文件中：
                                                    
                                                    "Redis": {
                                                        "Configuration": "127.0.0.1"
                                                    }
                    */


                    /*
                        三、使用方法

                                有两种方法使用分布式锁API： "ABP的IAbpDistributedLock 抽象 " 和 "分布式锁库的API"
                                    
                                
                                1、使用 IAbpDistributedLock 服务

                                        IAbpDistributedLock是ABP提供的一个简单服务，用于简单使用分布式锁。

                                        eg： 使用 IAbpDistributedLock.TryAAcquireAsync 方法

                                                using Volo.Abp.DistributedLocking; 

                                                namespace AbpDemo
                                                {
                                                    public class MyService : ITransientDependency
                                                    {
                                                        private readonly IAbpDistributedLock _distributedLock; // 注入分布式锁服务
                                                        public MyService(IAbpDistributedLock distributedLock)
                                                        {
                                                            _distributedLock = distributedLock; 
                                                        }
                                                        
                                                        public async Task MyMethodAsync()
                                                        {
                                                            await using (var handle = await _distributedLock.TryAcquireAsync("MyLockName")) // 获取锁
                                                            {
                                                                if (handle != null)
                                                                {
                                                                    // 访问多个应用程序的公共资源
                                                                }
                                                            }   
                                                        }
                                                    }
                                                }

                                        TryAcquireAsync 可能无法获取锁。如果无法获取锁，它会返回null。
                                        
                                        在这种情况下，你不应该访问资源。

                                        如果返回结果不为null,则表示你已经获得了锁，可以安全地访问资源。

                                        TryAcquireAsync方法获得一下参数：
                                                        
                                                        ①、name（string，必需）：你的锁的唯一名称。不同的命名锁用于访问不同的资源。

                                                        ②、timneOut (TimeSpan) ：等待获取锁的超时时间。 默认为 TimeSpan.Zero,这意味着已经被另一个应用程序拥有，它不会等待。

                                                        ③、cancellationToken (CancellationToken) ：用于取消操作的令牌。

                                2、配置

                                            ★、分布式锁配置类 AbpDistributedLockOptions
                                                                    
                                                    AbpDistributedLockOptions是配置分布式锁定的主要选项类。

                                                    eg： 为应用程序设置 "分布式锁密钥前缀"

                                                        Configure<AbpDistributedLockOptions>(options =>
                                                        {
                                                            options.KeyPrefix = "MyApp1"; // 指定锁名前缀
                                                        });

                                                        将代码写入模块类的 ConfigureServices 方法中。

                                                    可配置的选项：
                                                            
                                                            ①、KeyPrefix (string, default:null):  指定锁名前缀

                                3、使用分布式锁库的API

                                            ABP的IAbpDistributedLock服务非常有限，主要设计为ABP内部使用。

                                            对于你自己的应用程序，你可以使用分布式锁库自己的API。


                    */

                    /*
                        四、"Volo.Abp.DistributedLocking.Abstractions " 包 
                                                            
                                如果你正在构建一个可重用的库或一个应用程序模块，那么对于作为单个实例运行的简单应用程序，你可能不希望为你的模块带来额外的依赖项。

                                在这种情况下，你的库可以依赖于 "Volo.Abp.DistributedLocking.Abstractions "该包定义了IAbpDistributedLock服务并将其实现为进程内（实际上不是分布式的）。

                                。通过这种方式，你的库可以在作为单个实例运行的应用程序中正常运行（没有分布式锁提供程序依赖项）。
                        

                                如果应用程序部署到集群环境，那么应用程序开发人员应该安装一个真正的分布式提供程序，如安装部分所述。
                    */
        </script>
    </body>
</html>